/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
/**
 * \file
 * \brief FastProtocol types and structures.
 * \author Antti Maula <antti.maula@tkk.fi>
 */
#ifndef _FASTPROTOCOLHDR_H_
#define _FASTPROTOCOLHDR_H_
#include "protocolID.h"
#include <inttypes.h>

#define FASTPROTOCOL_NUMBER                            0x01

/**
 * When this flag is SET on outgoing packet, the HUB will
 * send ERROR REPORTS to sender. Possible error values
 * currently are: ERROR_LINK and ERROR_UNREACHABLE.
 * ( See their description )
 */
#define FASTPROTOCOL_FLAG_REPORT_ERROR                 PROTOCOL_FLAGBIT(0)


/**
 * When this flag is SET on outgoing packet, the HUB will
 * send status reports to sender. Possible status reports
 * are currently: STATUS_CONGESTION
 * ( See their description )
 */
#define FASTPROTOCOL_FLAG_REPORT_STATUS                PROTOCOL_FLAGBIT(1)


/**
 * If this flag is SET on incoming packet, this packet
 * is an STATUS REPORT. This packet carries no payload.
 * See the error type flag to determine the occured error.
 */
#define FASTPROTOCOL_FLAG_STATUS                       PROTOCOL_FLAGBIT(2)


/**
 * If this flag is SET on incoming packet, this packet
 * is an ERROR REPORT. This packet carries no payload.
 * See the status type flag to determine the occured event.
 */
#define FASTPROTOCOL_FLAG_ERROR                        PROTOCOL_FLAGBIT(3)


/**
 * If this flag is SET on incoming packet, it means that the
 * incoming packet is of type EXPLICIT_MULTICAST. This packet
 * has a special format:
 * - The 'target_client' field indicates the number of recipients
 *   for this packet.
 * - Recipients are listed AFTER header and BEFORE payload, so that
 *   each recipient address is fully qualified hubid (32 bits).
 *   Total size of extra recipients block is 'target_client * 4' bytes, 
 *   after which, the payload begins. NOTE: The address array MUST
 *   BE SORTED by HubID, otherwise the multicast will not work
 *   properly.
 * - The 'target_hub' field is reserved and should be left zero.
 * 
 * NOTE: The Multicast header is STRIPPED from the packet before
 * delivering to final recipient. The final recipient will only
 * receive an 'ordinary' dataframe with no knowledge of its multicast
 * origin.
 *
 * Note, this is specified as 'EXPLICIT' multicast, because every
 * packet must contain the target addresses. In the future, we may
 * implement a 'real', "flow-label" based multicast - IF required!
 */
#define FASTPROTOCOL_FLAG_MODE_EXPLICIT_MULTICAST      PROTOCOL_FLAGBIT(8)


/** 
 * If this flag is SET on incoming packet, it means that the incoming
 * frame is of type 'Broadcast'. This flag must be present before any
 * broadcast-specific processing is attempted on the frame.
 * This packet has special interpretation:
 *
 * - The 'target_client' field is interpreted to check whether this
 * packet is a GLOBAL or LOCAL broadcast. Global broadcast means a
 * packet which should be delivered to EVERY connected node on the
 * whole GIMnet. LOCAL broadcast means a packet which is delivered
 * only inside local tcpHub to all connected clients. If the
 * 'target_client' field contains only zeros ('target_client' == 0x00)
 * the packet is interpreted as global broadcast. If the HUB part of
 * address contains non-zero value, the packet is sent to this hub (or
 * processed locally in case of HubID match) to be processed as LOCAL
 * broadcast. The client part of target address is silently ignored.
 * :)
 */
#define FASTPROTOCOL_FLAG_MODE_BROADCAST               PROTOCOL_FLAGBIT(9)


/**
 * If this flag is SET on incoming packet, this packet is an
 * CONGESTION STATUS REPORT.  This packet carries no payload. When
 * this event happens, it means that the packet has been delayed
 * onroute to the destination.
 */
#define FASTPROTOCOL_FLAG_STATUS_CONGESTION            PROTOCOL_FLAGBIT(11)


/**
 * If this flag is SET on incoming packet, this packet is an LINK
 * ERROR REPORT. Link error report means that the packet encountered a
 * bad link during the route, and the target is unreachable (not very
 * big difference to ERROR_UNREACHABLE)
 */
#define FASTPROTOCOL_FLAG_ERROR_LINK                   PROTOCOL_FLAGBIT(14)


/**
 * If this flag is SET on incoming packet, this packet is an
 * UNREACHABLE ERROR REPORT. Unreachable error means, that the
 * destination target is unknown. (Is not known to exists, or no route
 * to target exists (no hub route for example))
 *
 * More distinct error types may be specified in the future.
 */
#define FASTPROTOCOL_FLAG_ERROR_UNREACHABLE            PROTOCOL_FLAGBIT(15)




#define FASTPROTOCOL_DEFAULT_TTL                       32

#define FASTPROTOCOL_PAYLOAD2TOTAL(xyz) \
        ((xyz) + sizeof(TFastProtocolHeader))
#define FASTPROTOCOL_TOTAL2PAYLOAD(xyz) \
        ((xyz) - sizeof(TFastProtocolHeader))

/**
 * Link level protocol over tcpHub. Contains necessary data for interHUB
 * routing.
 */
typedef struct _fastProtocolHeader
{
  TProtocolIdentification protocol_id; ///< ID sizes 4 bytes

  uint8_t statusvalue;           ///< Status value; Depends on flags.
  uint8_t ttl;                   ///< Time-To-Live (decremented on routing)
  uint16_t flags;            ///< Protocol flags

  union {
    uint32_t target_id;                ///< Target ID. May be broadcast target.
    uint32_t target_count;             ///< Target count. (Explicit multicast)
  };

  uint32_t source_id;                  ///< Source ID. Sender ID of this packet.
} TFastProtocolHeader;

#define SIZEOF_TFASTPROTOCOLHEADER (16)
#endif
